package me.itsoo.elasticbatis.binding;

import me.itsoo.elasticbatis.io.ResolverUtil;
import me.itsoo.elasticbatis.session.SqlSession;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * MapperRegistry
 *
 * @author zhangxy4
 * @version 0.0.1
 * @since 2025/4/3
 */
public class MapperRegistry {

    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();

    @SuppressWarnings("unchecked")
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
        if (mapperProxyFactory == null) {
            throw new RuntimeException("Type " + type + " is not known to the MapperRegistry.");
        }

        try {
            return mapperProxyFactory.newInstance(sqlSession);
        } catch (Exception e) {
            throw new RuntimeException("Error getting mapper instance. Cause: " + e, e);
        }
    }

    public <T> boolean hasMapper(Class<T> type) {
        return knownMappers.containsKey(type);
    }

    public <T> void addMapper(Class<T> type) {
        if (type.isInterface()) {
            if (hasMapper(type)) {
                throw new RuntimeException("Type " + type + " is already known to the MapperRegistry.");
            }

            knownMappers.put(type, new MapperProxyFactory<>(type));
        }
    }

    /**
     * 根据提供的包名，注册Mapper
     *
     * @param packageName 包名
     */
    public void addMappers(String packageName) {
        Set<Class<?>> mapperSet = ResolverUtil.findClasses(packageName);
        for (Class<?> mapperClass : mapperSet) {
            this.addMapper(mapperClass);
        }
    }
}
